//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.eResearch.Common.Linq
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Provides a few commonly-used extension methods for working with IEnumerable collections.
    /// </summary>
    public static class ExtensionMethods
    {
        /// <summary>
        /// Applies the specified action to each item in the source collection.
        /// </summary>
        /// <typeparam name="T">Any IEnumerable collection.</typeparam>
        /// <param name="source">The source collection.</param>
        /// <param name="action">The action to be applied to each element.</param>
        public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
        {
            foreach (T item in source)
            {
                action(item);
            }
        }

        /// <summary>
        /// Applies the specified action to each item in the source collection.
        /// </summary>
        /// <typeparam name="T">Any IEnumerable collection.</typeparam>
        /// <param name="source">The source collection.</param>
        /// <param name="action">The action to be applied to each element.</param>
        /// <returns>The original collection.</returns>
        public static IEnumerable<T> ForEachPassThrough<T>(this IEnumerable<T> source, Action<T> action)
        {
            foreach (T item in source)
            {
                action(item);
            }

            return source;
        }

        /// <summary>
        /// Applies the specified action to each item in the source collection.
        /// The action is passed the item index as well as the item.
        /// </summary>
        /// <typeparam name="T">Any IEnumerable collection.</typeparam>
        /// <param name="source">The source colleciton.</param>
        /// <param name="action">The action to be applied to each element.</param>
        public static void ForEachIndex<T>(this IEnumerable<T> source, Action<int, T> action)
        {
            int index = 0;
            foreach (T item in source)
            {
                action(index++, item);
            }            
        }

        /// <summary>
        /// Applies the specified action to each item in the source collection.
        /// The action is passed the item index, the collection count, and the item.
        /// </summary>
        /// <typeparam name="T">Any IEnumerable collection.</typeparam>
        /// <param name="source">The source.</param>
        /// <param name="action">The action.</param>
        public static void ForEachIndexCount<T>(this IEnumerable<T> source, Action<int, int, T> action)
        {
            int index = 0;
            int count = source.Count();
            foreach (T item in source)
            {
                action(index++, count, item);
            }
        }
    }
}
